package base.collection_demo.demo01;

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

/**
 * 集合中正确移除对象的几种方式
 */
public class Client2 {

    //删除集合中偶数数字 [1L,2L,2L,3L,3L,4L]
    // 采用纯索引获得和删除元素，控制好索引不错位即可。
    @Test
    public void testCase1(){
        ArrayList<Long> list =
                new ArrayList<>(Arrays.asList(1L,2L,2L,3L,3L,4L));//Arrays.asList()得到的列表不支持remove()，转换为ArrayList就支持了

        int i =0;
        while (i<list.size()){//每次遍历，最大值不能超过新数组的大小
            if (list.get(i)%2 == 0) {
                list.remove(i);//移除元素后，索引不变，下次判断还是该索引位置元素，但该索引位置元素是左移一位进来的新数据，不会遗漏数据
            }else{
                i++;
            }
        }

        System.out.println(list);//[1, 3, 3]
    }

    /*
     * list#remove(i) 逆序移除也是可行的.
     * 每次调用remove(int index)，index后面的元素会往前移动，如果是从后往前遍历，
     * index后面的元素发生移动，跟index前面的元素无关，我们循环只去和前面的元素做判断，因此就没有影响
     */
    @Test
    public void testCase2(){
        ArrayList<Long> list = new ArrayList<>(Arrays.asList(1L,2L,2L,3L,3L,4L));
        for (int i = list.size()-1; i >=0 ; i--) {
            Long aLong = list.get(i);
            if (aLong%2==0) {
                list.remove(i);
            }
        }
        System.out.println(list);//[1, 3, 3]
    }

    /*
     * Collection里面的removeAll()移除元素.
     * removeAll源码是这样的：定义了两个数组指针r和w，初始都指向列表第一个元素。循环遍历列表，r指向当前元素，若当前元素没有满足移除条件，
     * 将数组[r]元素赋值给数组[w]，w指针向后移动一位。这样就完成了整个数组中，没有被移除的元素向前移动。遍历完列表后，将w后面的元素都置空，
     * 并减少数组长度。至此完成removeAll移除操作。
     */
    @Test
    public void testCase3(){
        ArrayList<Long> removeList = new ArrayList<>();//临时存储要被移除的元素
        ArrayList<Long> list = new ArrayList<>(Arrays.asList(1L,2L,2L,3L,3L,4L));
        for (Long aLong : list) {
            if (aLong%2==0) {
                removeList.add(aLong);
            }
        }
        list.removeAll(removeList);
        System.out.println(list);//[1, 3, 3]
    }

    /*
     * 使用迭代器remove()方法
     */
    @Test
    public void testCase4(){
        ArrayList<Long> list = new ArrayList<>(Arrays.asList(1L,2L,2L,3L,3L,4L));
        Iterator<Long> iterator = list.iterator();
        while (iterator.hasNext()) {
            Long next = iterator.next();//next()方法是必须要调用的，即使不拿next%2==0做为比较条件，迭代器要想删除元素，必须调用迭代器的next()方法
            if (next%2==0) {
                iterator.remove();
            }
        }
        System.out.println(list);//[1, 3, 3]
    }


    /*
     * jdk1.8 removeIf() 方法移除集合中元素。
     * removeIf()的入参是一个过滤条件，用来判断需要移除的元素是否满足条件。方法中设置了一个removeSet，
     * 把满足条件的元素索引坐标都放入removeSet，然后统一对removeSet中的索引进行移除。源码相对复杂的是BitSet模型
     */
    @Test
    public void testCase5(){
        ArrayList<Long> list = new ArrayList<>(Arrays.asList(1L,2L,2L,3L,3L,4L));
        list.removeIf(x -> x % 2 == 0);
        System.out.println(list);//[1, 3, 3]
    }




}
